Imports System.Drawing.Printing
Imports System.Windows.Forms
Imports Vintasoft.Imaging
Imports Vintasoft.Imaging.Codecs
Imports Vintasoft.Imaging.Print

Namespace Imaging
	''' <summary>
	''' ThumbnailViewer print manager.
	''' </summary>
	Public Class ThumbnailViewerPrintManager

		#Region "Fields"

		' Array of images to print.
		Private _pagesToPrint As Integer()
		' Index of the printing page.
		Private _printPageIndex As Integer = 0
		' Rendering settings before print.
		Private _renderingSettingsBeforePrint As RenderingSettings

		Private _disposeCurrentImageAfterUse As Boolean

		Private _thumbnailViewer As ThumbnailViewer
		Private _imageViewer As ImageViewer
		Private _printDocument As ImagePrintDocument
		Private _printDialog As PrintDialog

		#End Region



		#Region "Contructor"

		Public Sub New(thumbnailViewer As ThumbnailViewer, printDocument As ImagePrintDocument, printDialog As PrintDialog)
			_thumbnailViewer = thumbnailViewer
			If _thumbnailViewer.MasterViewer IsNot Nothing AndAlso TypeOf _thumbnailViewer.MasterViewer Is ImageViewer Then
				_imageViewer = DirectCast(_thumbnailViewer.MasterViewer, ImageViewer)
			End If

			_printDialog = printDialog

			_printDocument = printDocument
			AddHandler _printDocument.BeginPrint, New PrintEventHandler(AddressOf printDocument_BeginPrint)
			AddHandler _printDocument.PrintImage, New EventHandler(Of PrintImageEventArgs)(AddressOf printDocument_PrintImage)
			AddHandler _printDocument.EndPrint, New PrintEventHandler(AddressOf printDocument_EndPrint)
			AddHandler _printDocument.ImagePrinted, New EventHandler(Of PrintImageEventArgs)(AddressOf printDocument_EndPrintImage)

			' no margins
			_printDocument.DefaultPageSettings.Margins = New Margins(0, 0, 0, 0)
		End Sub

		#End Region



		#Region "Properties"

		Private _imagesResolutionBeforePrint As Resolution()
		''' <summary>
		''' Gets an Images resolution before print.
		''' </summary>
		Public ReadOnly Property ImagesResolutionBeforePrint() As Resolution()
			Get
				Return _imagesResolutionBeforePrint
			End Get
		End Property

		#End Region



		#Region "Methods"

		Public Sub Print()
			If _thumbnailViewer.Images.Count = 0 Then
				Return
			End If
			If _pagesToPrint IsNot Nothing Then
				DemosTools.ShowWarningMessage("Another print process is still working.")
				Return
			End If

			_printDialog.PrinterSettings.FromPage = 1
			_printDialog.PrinterSettings.ToPage = _thumbnailViewer.Images.Count

			' show print dialog
			Dim dialogResult__1 As DialogResult = _printDialog.ShowDialog()

			' PrintDialog control has bug and sometimes does not show print dialog and returns
			' Cancel as a result of execution of the ShowDialog method. This problem can be solved
			' if you will set the UseEXDialog property to True.
			If dialogResult__1 = DialogResult.Cancel Then
				_printDialog.UseEXDialog = True
				dialogResult__1 = _printDialog.ShowDialog()
			End If

			' start print if dialog results is OK
			If dialogResult__1 = System.Windows.Forms.DialogResult.OK Then
				Select Case _printDialog.PrinterSettings.PrintRange
					Case PrintRange.AllPages
						_pagesToPrint = New Integer(_thumbnailViewer.Images.Count - 1) {}
						For i As Integer = 0 To _pagesToPrint.Length - 1
							_pagesToPrint(i) = i
						Next
						Exit Select

					Case PrintRange.SomePages
						_pagesToPrint = New Integer(_printDialog.PrinterSettings.ToPage - _printDialog.PrinterSettings.FromPage) {}
						For i As Integer = 0 To _pagesToPrint.Length - 1
							_pagesToPrint(i) = _printDialog.PrinterSettings.FromPage + i - 1
						Next
						Exit Select

					Case PrintRange.Selection
						If _thumbnailViewer.SelectedIndices.Count > 0 Then
							_pagesToPrint = _thumbnailViewer.SelectedIndices.ToArray()
						Else
							_pagesToPrint = New Integer(0) {_thumbnailViewer.FocusedIndex}
						End If
						Exit Select

					Case PrintRange.CurrentPage
						_pagesToPrint = New Integer(0) {_thumbnailViewer.FocusedIndex}
						Exit Select
				End Select
				_printDocument.Print()
			End If
		End Sub

		Protected Overridable Function GetImage(imageIndex As Integer, ByRef disposeAfterUse As Boolean) As VintasoftImage
			disposeAfterUse = False
			Return _thumbnailViewer.Images(imageIndex)
		End Function

		Private Sub printDocument_BeginPrint(sender As Object, e As PrintEventArgs)
			If _pagesToPrint.Length = 0 Then
				e.Cancel = True
			End If

			_printPageIndex = 0

			_imagesResolutionBeforePrint = New Resolution(_thumbnailViewer.Images.Count - 1) {}
			For i As Integer = 0 To _imagesResolutionBeforePrint.Length - 1
				_imagesResolutionBeforePrint(i) = _thumbnailViewer.Images(i).Resolution
			Next

			' remember resolution of rendering settings before print
			If _imageViewer IsNot Nothing Then
				_renderingSettingsBeforePrint = _imageViewer.RenderingSettings
			Else
				_renderingSettingsBeforePrint = _thumbnailViewer.Images(0).RenderingSettings
			End If
			' get resolution of the printer
			Dim printerResolution As PrinterResolution = DirectCast(sender, ImagePrintDocument).DefaultPageSettings.PrinterResolution
			Dim renderingResolution As Resolution = _renderingSettingsBeforePrint.Resolution
			' set resolution of the rendering settings to printer resolution 
			' if current resolution of rendering settings is not equal printer resolution
			If printerResolution.X > 0 AndAlso printerResolution.Y > 0 Then
				If printerResolution.X <> renderingResolution.Horizontal OrElse printerResolution.Y <> renderingResolution.Vertical Then
					_thumbnailViewer.Images.SetRenderingSettings(New RenderingSettings(printerResolution.X, printerResolution.Y, _renderingSettingsBeforePrint.InterpolationMode, _renderingSettingsBeforePrint.SmoothingMode))
				End If
			End If
		End Sub

		Private Sub printDocument_PrintImage(sender As Object, e As Vintasoft.Imaging.Print.PrintImageEventArgs)
			' if there are images to print
			If _pagesToPrint.Length > 0 Then
				Dim hasMoreImages As Boolean = True

				' get the printed image
				Dim imageIndex As Integer = _pagesToPrint(_printPageIndex)
				If imageIndex >= _thumbnailViewer.Images.Count Then
					e.HasMoreImages = False
					Return
				End If
				Try
					e.Image = GetImage(imageIndex, _disposeCurrentImageAfterUse)
				Catch generatedExceptionName As DecoderException
					hasMoreImages = False
				End Try
				' increment the count of printed pages
				_printPageIndex += 1

				' check if there is more images to print
				If hasMoreImages AndAlso (_printPageIndex >= _pagesToPrint.Length) Then
					hasMoreImages = False
				End If
				e.HasMoreImages = hasMoreImages
			End If
		End Sub

		Private Sub printDocument_EndPrintImage(sender As Object, e As PrintImageEventArgs)
			If _disposeCurrentImageAfterUse Then
				e.Image.Dispose()
			End If
		End Sub

		Private Sub printDocument_EndPrint(sender As Object, e As PrintEventArgs)
			' clear array of pages to print
			_pagesToPrint = Nothing
			_printPageIndex = 0
			' restore rendering settings
			_thumbnailViewer.Images.SetRenderingSettings(_renderingSettingsBeforePrint)
		End Sub

		#End Region

	End Class
End Namespace
